"""
## 无监督聚类API-Kmeans
# 1 导包 sklearn.cluster.KMeans sklearn.datasets.make_blobs#
# 2 创建数据集
# 2-1 展示数据效果
# 3 实例化Kmeans模型并预测
# 3-1 展示聚类效果
# 4 评估3种聚类效果好坏
"""
# 导入依赖包
from sklearn.cluster import KMeans
# make系列-自己构造数据集 fetch系列大数据-从网络加载 load系列小数据集-从本地数据集
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
from sklearn.metrics import calinski_harabasz_score  # calinski_harabaz_score 废弃


def dm04_kmeans():
    # 2.创建数据集
    # n_samples=1000: 生成1000个样本点
    # n_features=2: 每个样本有2个特征（即二维数据，可以在平面上可视化）
    # centers=[[-1, -1], [0, 0], [1, 1], [2, 2]]: 定义了4个聚类中心的坐标
    # 第1个聚类中心在坐标(-1, -1)
    # 第2个聚类中心在坐标(0, 0)
    # 第3个聚类中心在坐标(1, 1)
    # 第4个聚类中心在坐标(2, 2)
    # cluster_std=[0.4, 0.2, 0.2, 0.2]: 定义了各个聚类的标准差
    # 第1个聚类的标准差是0.4（较分散）
    # 其余3个聚类的标准差是0.2（较紧凑）
    # random_state=22: 设置随机种子为22，确保每次运行代码生成的数据集相同

    # 返回值
    # x: 返回的是形状为(1000, 2)的数组，包含1000个样本点的坐标
    # y: 返回的是形状为(1000,)的数组，包含每个样本点所属的聚类标签(0, 1, 2, 3)
    x, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1, -1], [0, 0], [1, 1], [2, 2]],cluster_std=[0.4, 0.2, 0.2, 0.2], random_state=22)
    # print(y)
    plt.figure()
    plt.scatter(x[:,0],x[:,1],marker='o')
    plt.show()

    # 3 使用k-means进行聚类, 并使用CH方法评估
    # n_clusters=2：
    #   尽管原始数据有4个聚类中心，这里指定只分成2个簇
    #   这可能是为了测试算法在簇数量不匹配实际情况时的表现
    # random_state=22：
    #   设置随机种子，确保每次运行结果一致
    #   对于研究和调试非常有用
    # init='k-means++'：
    #   选择初始聚类中心的方法
    #   k-means++算法会选择相互之间距离较远的点作为初始聚类中心
    #   比随机选择初始点更有效，可以加速收敛并获得更好的结果
    # n_init='auto'：
    #   指定算法运行的次数，每次使用不同的初始中心点
    #   'auto'表示自动决定运行次数
    #   多次运行可以避免陷入局部最优解
    # fit_predict(x)：
    #   在数据x上训练模型并返回每个样本的聚类标签
    #   返回的y_pred是一个包含0和1的数组（因为n_clusters=2）

    # 3-1 n_clusters=2
    y_pred = KMeans(n_clusters=2, random_state=22, init='k-means++', n_init='auto').fit_predict(x)
    plt.scatter(x[:, 0], x[:, 1], c=y_pred)
    plt.show()
    # calinski_harabasz_score(x, y_pred)：
    #   计算Calinski-Harabasz指数，也称为方差比准则
    #   计算公式：簇间离散度/簇内离散度 * (N-k)/(k-1)
    #     - N是样本数
    #     - k是簇的数量
    #   值越高表示聚类效果越好，即簇内更紧凑，簇间更分离
    #   这是一种内部评估指标，不需要真实标签
    print('1-->', calinski_harabasz_score(x, y_pred))

    # 3-2 n_clusters=3
    y_pred = KMeans(n_clusters=3, random_state=22, n_init='auto').fit_predict(x)
    plt.scatter(x[:, 0], x[:, 1], c=y_pred)
    plt.show()
    print('2-->', calinski_harabasz_score(x, y_pred))

    # 3-3 n_clusters=4
    y_pred = KMeans(n_clusters=4, random_state=22, n_init='auto').fit_predict(x)
    plt.scatter(x[:, 0], x[:, 1], c=y_pred)
    plt.show()
    print('3-->', calinski_harabasz_score(x, y_pred))
    
    


if __name__ == '__main__':
    dm04_kmeans()